package com.liuceng.zen.common.utils;


import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.Random;

import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.binary.Hex;
import org.apache.commons.lang3.StringEscapeUtils;

/**
 * @类功能说明：编码通用类EncodeUtils,集成Commons-Codec,Commons-Lang及JDK提供的编解码方法. @版本：V1.0
 */
public class EncodeUtils {

  private static final String DEFAULT_URL_ENCODING = "UTF-8";

  /**
   * 函数功能: Hex编码
   */
  public static String hexEncode(byte[] input) {
    return Hex.encodeHexString(input);
  }

  /**
   * 函数功能: Hex解码
   */
  public static byte[] hexDecode(String input) {
    try {
      return Hex.decodeHex(input.toCharArray());
    } catch (DecoderException e) {
      throw new IllegalStateException("Hex Decoder exception", e);
    }
  }

  /**
   * 函数功能: Base64编码
   */
  public static String base64Encode(byte[] input) {
    return new String(Base64.encodeBase64(input));
  }

  /**
   * 函数功能: Base64编码, URL安全(将Base64中的URL非法字符如+,/=转为其他字符, 见RFC3548)
   */
  public static String base64UrlSafeEncode(byte[] input) {
    return Base64.encodeBase64URLSafeString(input);
  }

  /**
   * 函数功能: Base64解码
   */
  public static byte[] base64Decode(String input) {
    return Base64.decodeBase64(input);
  }

  /**
   * 函数功能: URL 编码, Encode默认为UTF-8
   */
  public static String urlEncode(String input) {
    return urlEncode(input, DEFAULT_URL_ENCODING);
  }

  /**
   * 函数功能: URL 编码
   */
  public static String urlEncode(String input, String encoding) {
    try {
      return URLEncoder.encode(input, encoding);
    } catch (UnsupportedEncodingException e) {
      throw new IllegalArgumentException("Unsupported Encoding Exception", e);
    }
  }

  /**
   * 函数功能: URL 解码, Encode默认为UTF-8
   */
  public static String urlDecode(String input) {
    return urlDecode(input, DEFAULT_URL_ENCODING);
  }

  /**
   * 函数功能: URL 解码
   */
  public static String urlDecode(String input, String encoding) {
    try {
      return URLDecoder.decode(input, encoding);
    } catch (UnsupportedEncodingException e) {
      throw new IllegalArgumentException("Unsupported Encoding Exception", e);
    }
  }

  /**
   * 函数功能: Html 转码
   */
  public static String htmlEscape(String html) {
    return StringEscapeUtils.escapeHtml3(html);
  }

  /**
   * 函数功能: Html 解码
   */
  public static String htmlUnescape(String htmlEscaped) {
    return StringEscapeUtils.unescapeHtml3(htmlEscaped);
  }

  /**
   * 函数功能: Xml 转码
   */
  public static String xmlEscape(String xml) {
    return StringEscapeUtils.escapeXml11(xml);
  }

  /**
   * 函数功能: Xml 解码
   */
  public static String xmlUnescape(String xmlEscaped) {
    return StringEscapeUtils.unescapeXml(xmlEscaped);
  }

  /**
   * 函数功能: MD5签名
   */
  public static String testDigest(String myinfo) {
    byte[] digesta = null;
    try {
      java.security.MessageDigest alga = java.security.MessageDigest.getInstance("MD5");
      alga.update(myinfo.getBytes("gbk"));
      digesta = alga.digest();
    } catch (UnsupportedEncodingException e) {
      System.out.println("-----------------------------------------------");
      System.out.println("MD5发生错误！");
      System.out.println("-----------------------------------------------");
      return null;
    } catch (java.security.NoSuchAlgorithmException ex) {
      System.out.println("-----------------------------------------------");
      System.out.println("MD5发生错误！");
      System.out.println("-----------------------------------------------");
      return null;
    }
    return byte2hex(digesta);
  }

  /**
   * 函数功能: MD5签名
   */
  public static String testDigest(String myinfo, String encode)
      throws UnsupportedEncodingException {
    byte[] digesta = null;
    try {
      java.security.MessageDigest alga = java.security.MessageDigest.getInstance("MD5");
      alga.update(myinfo.getBytes(encode));
      digesta = alga.digest();

    } catch (java.security.NoSuchAlgorithmException ex) {
      System.out.println("MD5发生错误！");
      return null;
    }
    return byte2hex(digesta);
  }

  /**
   * 函数功能: 二进制转为十六进制串
   */
  public static String byte2hex(byte[] b) {
    String hs = "";
    String stmp = "";
    for (int n = 0; n < b.length; n++) {
      stmp = (java.lang.Integer.toHexString(b[n] & 0XFF));
      if (stmp.length() == 1) {
        hs = hs + "0" + stmp;
      } else {
        hs = hs + stmp;
      }
      if (n < b.length - 1) {
        // hs = hs;
      }
    }
    return hs;
  }

  /**
   * 函数功能: 生成随即密码
   */
  public static String genRandomNum(int pwd_len) {
    // 35是因为数组是从0开始的，26个字母+10个数字
    final int maxNum = 10;
    int i; // 生成的随机数
    int count = 0; // 生成的密码的长度
    /*
     * char[] str = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
     * 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6',
     * '7', '8', '9' };
     */

    char[] str = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};

    StringBuffer pwd = new StringBuffer("");
    Random r = new Random();
    r.setSeed(System.currentTimeMillis());
    while (count < pwd_len) {
      // 生成随机数，取绝对值，防止生成负数，

      i = Math.abs(r.nextInt(maxNum)); // 生成的数最大为36-1

      if (i >= 0 && i < str.length) {
        pwd.append(str[i]);
        count++;
      }
    }

    return pwd.toString();
  }

  // 易宝特殊md5签名方式
  public static String hmacSign(String aValue, String aKey) {
    byte k_ipad[] = new byte[64];
    byte k_opad[] = new byte[64];
    byte keyb[];
    byte value[];
    try {
      keyb = aKey.getBytes("UTF-8");
      value = aValue.getBytes("UTF-8");
    } catch (UnsupportedEncodingException e) {
      keyb = aKey.getBytes();
      value = aValue.getBytes();
    }

    Arrays.fill(k_ipad, keyb.length, 64, (byte) 54);
    Arrays.fill(k_opad, keyb.length, 64, (byte) 92);
    for (int i = 0; i < keyb.length; i++) {
      k_ipad[i] = (byte) (keyb[i] ^ 0x36);
      k_opad[i] = (byte) (keyb[i] ^ 0x5c);
    }

    MessageDigest md = null;
    try {
      md = MessageDigest.getInstance("MD5");
    } catch (NoSuchAlgorithmException e) {

      return null;
    }
    md.update(k_ipad);
    md.update(value);
    byte dg[] = md.digest();
    md.reset();
    md.update(k_opad);
    md.update(dg, 0, 16);
    dg = md.digest();
    return toHex(dg);
  }

  public static String toHex(byte input[]) {
    if (input == null)
      return null;
    StringBuffer output = new StringBuffer(input.length * 2);
    for (int i = 0; i < input.length; i++) {
      int current = input[i] & 0xff;
      if (current < 16)
        output.append("0");
      output.append(Integer.toString(current, 16));
    }

    return output.toString();
  }

  // 以上即是易宝md5签名方式
  public static void main(String saf[]) {
    String usercodeString = "A672353";
    String pass = "ofcardpay";
    pass = testDigest(pass);
    System.out.println(pass);
    System.out.println(pass.length());
    String psw = "c012032ddcee83f8969683f98be51ea6ff55e70dd5320a8a0aeef4a203a36c65";
    String result = testDigest(usercodeString + pass + psw);
    System.out.println(result);
    System.out.println(testDigest(
        "A672353r1.0cp1319595089906R11102610113010020004015123456789012345http://localhost:8088/ofrcvcardnotify.do2001数据接收成功,验证卡密中20111026101130"));
  }
}
